package cc.rengu.igas.channel.cups.core.service.trans;

import cc.rengu.igas.channel.cups.common.constant.CupsParamConstant;
import cc.rengu.igas.channel.cups.common.constant.CupsTreeNodeConstant;
import cc.rengu.igas.channel.cups.common.enums.RespCodeEnum;
import cc.rengu.igas.channel.cups.core.model.ChnlBizResponse;
import cc.rengu.igas.channel.cups.core.model.CupsFieldRspBean;
import cc.rengu.igas.channel.cups.core.realize.CupsMacService;
import cc.rengu.igas.channel.cups.core.realize.impl.CupsMacServiceImpl;
import cc.rengu.igas.channel.cups.core.service.base.BaseNoticeService;
import cc.rengu.igas.channel.cups.facade.request.SignResultNoticeRequest;
import cc.rengu.igas.channel.cups.facade.request.TokenSignOffNoticeRequest;
import cc.rengu.igas.channel.cups.facade.response.SignResultNoticeResponse;
import cc.rengu.igas.channel.cups.facade.response.TokenSignOffNoticeResponse;
import cc.rengu.igas.share.facade.bean.CupsField;
import cc.rengu.igas.share.facade.bean.CupsFieldBean;
import cc.rengu.igas.share.facade.bean.cups.F60_2_1_AccountTypeEnum;
import cc.rengu.igas.share.facade.bean.cups.F60_2_8_ECIEnum;
import cc.rengu.jradp.mods.trmsg.iso8583.MacUtil;
import cc.rengu.jradp.schedule.ScheduleImpl;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.entity.DstChannelInfo;
import cc.rengu.oltp.service.common.entity.KeyInfo;
import cc.rengu.oltp.service.common.enums.OltpRpcdEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.utility.util.BeanUtil;
import cc.rengu.oltp.utility.util.ConvertUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;
import cc.rengu.utility.cache.UnifiedCache;

/**
 * 单位token解约通知
 *
 * @author GJS
 * @version 1.0
 * @date 2021/4/23
 */
public class TokenSignOffNoticeService extends BaseNoticeService {
    @Override
    protected Object beforeBizProcess() throws Exception {
        TokenSignOffNoticeRequest signOffNoticeRequest = new TokenSignOffNoticeRequest();
        ConvertUtil.convertOutput(signOffNoticeRequest);
        return signOffNoticeRequest;
    }

    @Override
    protected ChnlBizResponse callBizService(Object request) throws Exception {
        TokenSignOffNoticeRequest signOffNoticeRequest = (TokenSignOffNoticeRequest) request;
        return directCups(signOffNoticeRequest);
    }

    @Override
    protected void afterBizProcess(ChnlBizResponse response) throws Exception {
        TokenSignOffNoticeResponse signOffNoticeResponse = (TokenSignOffNoticeResponse) response.getResult();
        ConvertUtil.convertInput(signOffNoticeResponse);
    }

    /**
     * 直连cups
     *
     * @param tokenSignOffNoticeRequest
     * @return
     * @throws Exception
     */
    ChnlBizResponse directCups(TokenSignOffNoticeRequest tokenSignOffNoticeRequest) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        int iReturnCode = 0;
        ChnlBizResponse chnlBizResponse = new ChnlBizResponse();
        TokenSignOffNoticeResponse signOffNoticeResponse = new TokenSignOffNoticeResponse();
        DstChannelInfo dstChannelInfo = (DstChannelInfo) xmlTreeUtil.getXmlTreeObjectValue(CupsTreeNodeConstant.DST_CHANNEL_INFO, DstChannelInfo.class);

        CupsFieldBean cupsFieldBean = new CupsFieldBean();
        CupsField cupsField = new CupsField();
        cupsFieldBean.setCupsField(cupsField);

        BeanUtil.beanCopy(tokenSignOffNoticeRequest, cupsField);
        cupsField.setMsgType("0220");
        String origAcqInstIdCode = tokenSignOffNoticeRequest.getAcqInstCode();
        /*if (origAcqInstIdCode.length() < CupsParamConstant.CUPS_INSTIDCODE_FILL_LEN) {
            origAcqInstIdCode = String.format("%0" + (11 - origAcqInstIdCode.length()) + "d", 0) + origAcqInstIdCode;
        }*/
        String origFwdInstCode = tokenSignOffNoticeRequest.getFwdInstCode();
        /*if (origFwdInstCode.length() < CupsParamConstant.CUPS_INSTIDCODE_FILL_LEN) {
            origFwdInstCode = String.format("%0" + (11 - origFwdInstCode.length()) + "d", 0) + origFwdInstCode;
        }*/

        //TODO 0110 、0100
        cupsField.setOrigData("0100" + tokenSignOffNoticeRequest.getOrigTxnInfo().getOriTransDateTime() + tokenSignOffNoticeRequest.getOrigTxnInfo().getOriCupsTraceNo() +
                origAcqInstIdCode + origFwdInstCode);
        //TODO 原数据元赋值待确认
        cupsField.setOrigData("010012690304221932510000000499124000000004991240");

        /*
         * TODO
         * AS+AO用法， 用于标识签约交易关联的后续交易。09-代收28-余额查询
         * 当AS+AO=09时， AS+PZ用法出现，用于传递签约信息。其中，用户号码用于填写商户给账户方分配的编号。 扣款方式、扣款比例用于填写账户的扣款方式。
         * */
        //cupsField.setPrivAddData(HexUtil.StringtoHex("ASAO00209"));

        // TODO F60赋值 F60.2.8=81（同意授权） F60.2.8=80（拒绝授权）
        cupsFieldBean.createF60().setF60_2_1(F60_2_1_AccountTypeEnum._4.getCode())
                .setF60_2_8(F60_2_8_ECIEnum._81.getCode());
        cupsFieldBean.build();

        ConvertUtil.convertInput(cupsFieldBean);

        xmlTreeUtil.setXmlTreeStringValue(CupsTreeNodeConstant.CUPS_MACBLOCK_ORIG_DATA_ELEMTS, cupsField.getOrigData().substring(0, 20));

        /*计算macblock*/
        MacUtil commonMac = (MacUtil) UnifiedCache.get(CupsParamConstant.CUPS_8583_MAC_CACHE_NAME,
                CupsParamConstant.CUPS_8583_MAC_FILE +
                        CupsParamConstant.CUPS_8583_MAC_TYPE_COMMON);
        byte[] macBlock = commonMac.genMacBlock(CupsParamConstant.CUPS_8583_MAC_TYPE_COMMON);
        if (macBlock == null) {
            throw new BizException(RespCodeEnum.GENERATE_MAC_BLOCK_ERROR.getRespCode(), RespCodeEnum.GENERATE_MAC_BLOCK_ERROR.getRespDesc());
        }
        xmlTreeUtil.setXmlTreeStringValue(CupsTreeNodeConstant.CUPS_MAC_BLOCK, new String(macBlock, CupsParamConstant.GB18030));

        String oriTxnNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TXN_NUM);
        xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TXN_NUM, tokenSignOffNoticeRequest.getHeader().getTxnNum());
        iReturnCode = schedule.callService(dstChannelInfo.getDstServiceName(), 0);
        /* 还原交易码 */
        xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TXN_NUM, oriTxnNum);
        if (ScheduleImpl.SERVICE_TIMEOUT == iReturnCode) {
            rglog.error("调用银联cups服务<{}>超时，iReturnCode:<{}>", dstChannelInfo.getDstServiceName(), iReturnCode);
            signOffNoticeResponse.setRespCode(OltpRpcdEnum.BIZ_PROCESS_TIMEOUT.getRespCode());
            signOffNoticeResponse.setRespDesc(OltpRpcdEnum.BIZ_PROCESS_TIMEOUT.getRespDesc());
            chnlBizResponse.setResult(signOffNoticeResponse);
            return chnlBizResponse;
        } else if (0 != iReturnCode) {
            rglog.error("调用银联cups服务<{}>失败，iReturnCode:<{}>", dstChannelInfo.getDstServiceName(), iReturnCode);
            throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
        }

        String tunlSsn = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.CHANNEL_SEQ_NUM);
        UnifiedCache.remove(CupsParamConstant.CACHE_CUPS_SN, tunlSsn);

        CupsFieldRspBean cupsFieldRspBean = new CupsFieldRspBean();
        ConvertUtil.convertOutput(cupsFieldRspBean);
        String mac = cupsFieldRspBean.getCupsFieldRsp().getMac();
        /*生成应答macBlock*/
        byte[] macBlockRsp = commonMac.getMacBlock(CupsParamConstant.CUPS_8583_MAC_TYPE_COMMON);
        CupsMacService cupsMacService = new CupsMacServiceImpl();
        KeyInfo keyInfo = (KeyInfo) xmlTreeUtil.getXmlTreeObjectValue(CupsTreeNodeConstant.CUPS_MAC_KEY_INFO, KeyInfo.class);
        boolean flag = cupsMacService.verifyMacString(keyInfo, mac, new String(macBlockRsp, CupsParamConstant.GB18030));
        if (!flag) {
            rglog.error("验证mac失败");
        }
        //signResultNoticeResponse.setVerifyMacFlag(flag);

        CupsField cupsFieldRsp = cupsFieldRspBean.getCupsFieldRsp();
        BeanUtil.beanCopy(cupsFieldRsp, signOffNoticeResponse);
        signOffNoticeResponse.setRespCode(cupsFieldRsp.getRespCode());

        if (CupsParamConstant.SUCCESS_CODE.equals(signOffNoticeResponse.getRespCode())) {
            signOffNoticeResponse.setRespCode(OltpRpcdEnum.TRANS_SUCCESS.getRespCode());
            signOffNoticeResponse.setRespDesc(OltpRpcdEnum.TRANS_SUCCESS.getRespDesc());
        }
        chnlBizResponse.setResult(signOffNoticeResponse);
        return chnlBizResponse;
    }

}
